package com.summli.basic.class07;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;

/**
 * 树的最宽度
 * 求二叉树最宽的层有多少个节点
 */
public class Code06_TreeMaxWidth {
    public static class Node {
        public int value;
        public Node left;
        public Node right;

        public Node(int data) {
            this.value = data;
        }
    }

    /*
    可以使用Map记录当前的Node处于的层数
     */
    public static int maxWidthUseMap(Node head) {
        if(head == null){
            return 0;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        Map<Node,Integer> map = new HashMap<>();
        map.put(head, 1);
        int result = 0;
        int curLeveSubNum = 0;
        int curLevel = 1;
        while(!queue.isEmpty()){
            Node poll = queue.poll();
            if(poll.left != null){
                queue.add(poll.left);
                map.put(poll.left, map.get(poll)+1);
            }
            if(poll.right != null){
                queue.add(poll.right);
                map.put(poll.right, map.get(poll)+1);
            }
            if(curLevel != map.get(poll)){
                result = Math.max(result, curLeveSubNum);
                curLeveSubNum = 1;
                curLevel++;
            }else{
                curLeveSubNum ++;
            }
        }
        return Math.max(result, curLeveSubNum);
    }

    /*
    主要是能记录每一层的结束位置，这样就可以在不同层的节点数量
     */
    public static int maxWidthNoMap(Node head) {
        if(head == null){
            return 0;
        }
        Queue<Node> queue = new LinkedList<>();
        queue.add(head);
        Node curEnd = head;
        Node nextENd = null;
        int curLevelCount = 0;
        int max = 0;
        while(!queue.isEmpty()){
            Node poll = queue.poll();
            if(poll.left!=null){
                queue.add(poll.left);
                nextENd = poll.left;
            }
            if(poll.right != null){
                queue.add(poll.right);
                nextENd = poll.right;
            }
            curLevelCount++;
            if(poll == curEnd){
                curEnd = nextENd;
                max= Math.max(max, curLevelCount);
                curLevelCount = 0;
            }
        }
        return max;
    }
    // for test
    public static Node generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static Node generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        Node head = new Node((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    public static void main(String[] args) {
        int maxLevel = 10;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
                Node head = generateRandomBST(maxLevel, maxValue);
            if (maxWidthUseMap(head) != maxWidthNoMap(head)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");

    }
}
